package com.ruoyi.baselibrary.infobasecategory.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.baselibrary.infobasecategory.mapper.InfoBaseCategoryMapper;
import com.ruoyi.baselibrary.infobasecategory.service.IInfoBaseCategoryService;
import com.ruoyi.baselibrary.infobasecategory.domain.InfoBaseCategory;
import com.ruoyi.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * 基础库类别树信息Service业务层处理
 *
 * @author ruoyi
 * @date 2022-01-11
 */
@Service
public class InfoBaseCategoryServiceImpl implements IInfoBaseCategoryService {
    private static final Logger log = LoggerFactory.getLogger(InfoBaseCategoryServiceImpl.class);
    @Autowired
    private InfoBaseCategoryMapper infoBaseCategoryMapper;

    /**
     * 查询基础库类别树信息
     *
     * @param id 基础库类别树信息主键
     * @return 基础库类别树信息
     */
    @Override
    public InfoBaseCategory selectInfoBaseCategoryById(Long id) {
        return infoBaseCategoryMapper.selectInfoBaseCategoryById(id);
    }

    /**
     * 查询基础库类别树信息列表
     *
     * @param infoBaseCategory 基础库类别树信息
     * @return 基础库类别树信息
     */
    @Override
    public List<InfoBaseCategory> selectInfoBaseCategoryList(InfoBaseCategory infoBaseCategory) {
        return infoBaseCategoryMapper.selectInfoBaseCategoryList(infoBaseCategory);
    }

    /**
     * 新增基础库类别树信息
     *
     * @param infoBaseCategory 基础库类别树信息
     * @return 结果
     */
    @Override
    public int insertInfoBaseCategory(InfoBaseCategory infoBaseCategory) {
        if (StringUtils.isNull(infoBaseCategory.getParentId())){
            infoBaseCategory.setParentId(0l);
        }
        if (infoBaseCategory.getParentId().compareTo(0l) == 0) {
            //顶级节点
            infoBaseCategory.setAncestors("0");
        } else {
            //非顶级节点 在具体节点下面
            //获取父节点的祖级
            InfoBaseCategory parent = infoBaseCategoryMapper.selectInfoBaseCategoryById(infoBaseCategory.getParentId());
            infoBaseCategory.setAncestors(parent.getAncestors() + "," + infoBaseCategory.getParentId());
        }
        infoBaseCategory.setCreateTime(DateUtils.getNowDate());
        infoBaseCategory.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        int i = infoBaseCategoryMapper.insertInfoBaseCategory(infoBaseCategory);
        infoBaseCategoryMapper.updateInfoBaseCategory(infoBaseCategory);
        restBaseCategoryCache();
        return i;
    }

    /**
     * 修改基础库类别树信息
     *
     * @param infoBaseCategory 基础库类别树信息
     * @return 结果
     */
    @Override
    public int updateInfoBaseCategory(InfoBaseCategory infoBaseCategory) {
        if (infoBaseCategory.getParentId().compareTo(0l) == 0) {
            //顶级节点
            infoBaseCategory.setAncestors("0");
            //查询父节点为这个id的
            infoBaseCategory.setAncestors("0");
            infoBaseCategoryMapper.updateInfoBaseCategory(infoBaseCategory);
            //递归更新
            recursionUpdateCategoryAncestors(infoBaseCategory.getId());
        } else {
            //非顶级节点 在具体节点下面
            //获取父节点的祖级
            InfoBaseCategory newParentCategory = infoBaseCategoryMapper.selectInfoBaseCategoryById(infoBaseCategory.getParentId());
            InfoBaseCategory oldCategory = infoBaseCategoryMapper.selectInfoBaseCategoryById(infoBaseCategory.getId());
            if (StringUtils.isNotNull(newParentCategory) && StringUtils.isNotNull(oldCategory)) {
                String newAncestors = newParentCategory.getAncestors() + "," + newParentCategory.getId();
                String oldAncestors = oldCategory.getAncestors();
                infoBaseCategory.setAncestors(newAncestors);
                updateCategoryChildren(infoBaseCategory.getId(), newAncestors, oldAncestors);
            }
        }
        infoBaseCategory.setUpdateTime(DateUtils.getNowDate());
        infoBaseCategory.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        int i = infoBaseCategoryMapper.updateInfoBaseCategory(infoBaseCategory);
        restBaseCategoryCache();
        return i;
    }

    /**
     * 递归
     *
     * @param id
     */
    private void recursionUpdateCategoryAncestors(Long id) {
        InfoBaseCategory parent = infoBaseCategoryMapper.selectInfoBaseCategoryById(id);
        InfoBaseCategory category = new InfoBaseCategory();
        category.setParentId(id);
        List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectInfoBaseCategoryList(category);
        if (infoBaseCategories.size() != 0) {
            for (InfoBaseCategory infoBaseCategory : infoBaseCategories) {
                infoBaseCategory.setAncestors(parent.getAncestors() + "," + parent.getId());
                updateInfoBaseCategory(infoBaseCategory);
                recursionUpdateCategoryAncestors(infoBaseCategory.getId());
            }
        }
    }

    /**
     * 修改子元素关系
     *
     * @param id           被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateCategoryChildren(Long id, String newAncestors, String oldAncestors) {
        List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectChildrenCategoryById(id);
        for (InfoBaseCategory child : infoBaseCategories) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (infoBaseCategories.size() > 0) {
            infoBaseCategoryMapper.updateCategoryChildren(infoBaseCategories);
        }
    }

    /**
     * 批量删除基础库类别树信息
     *
     * @param ids 需要删除的基础库类别树信息主键
     * @return 结果
     */
    @Override
    public int deleteInfoBaseCategoryByIds(Long[] ids) {
        //先判断下面是否含有子级
        for (Long id : ids) {
            InfoBaseCategory infoBaseCategory = new InfoBaseCategory();
            infoBaseCategory.setParentId(id);
            List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectInfoBaseCategoryList(infoBaseCategory);
            if (infoBaseCategories.size() != 0) {
                //说明含有子级 不允许删除
                throw new ServiceException("含有子级,不允许删除");
            }
        }
        int i = infoBaseCategoryMapper.deleteInfoBaseCategoryByIds(ids);
        restBaseCategoryCache();
        return i;
    }

    /**
     * 删除基础库类别树信息信息
     *
     * @param id 基础库类别树信息主键
     * @return 结果
     */
    @Override
    public int deleteInfoBaseCategoryById(Long id) {
        InfoBaseCategory infoBaseCategory = new InfoBaseCategory();
        infoBaseCategory.setParentId(id);
        List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectInfoBaseCategoryList(infoBaseCategory);
        if (infoBaseCategories.size() != 0) {
            //说明含有子级 不允许删除
            throw new ServiceException("含有子级,不允许删除");
        }
        restBaseCategoryCache();
        return infoBaseCategoryMapper.deleteInfoBaseCategoryById(id);
    }

    /**
     * 重置基础库类别redis缓存
     */
    public void restBaseCategoryCache() {
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        //1.清除所有的基础库类别缓存
        Collection<String> keys = redisCache.keys(Constants.BASE_CATEGORY_KEY);
        redisCache.deleteObject(keys);
        //2.查看所有的数据
        InfoBaseCategory infoBaseCategory = new InfoBaseCategory();
        List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectInfoBaseCategoryList(infoBaseCategory);
        redisCache.setCacheList(Constants.BASE_CATEGORY_KEY, infoBaseCategories);
        log.info("基础库类别缓存加载完毕");
    }

    /**
     * 根据基础库类别id获取  基础库/xxx/xxx
     *
     * @param categoryId 基础库类别id
     * @return
     */
    public String getBaseCategoryName(Long categoryId) {
        StringBuilder result = new StringBuilder();
        String lastCategoryName = "";
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        //1.获取该类型的缓存集合
        List<Object> cacheList = redisCache.getCacheList(Constants.BASE_CATEGORY_KEY);
        List<String> parentIds = new ArrayList<>();
        if (cacheList.size() == 0) {
            //刷新缓存
            restBaseCategoryCache();
            //在调取一次
            getBaseCategoryName(categoryId);
        } else {
            for (Object o : cacheList) {
                if (o instanceof InfoBaseCategory) {
                    InfoBaseCategory infoBaseCategory = (InfoBaseCategory) o;
                    if (infoBaseCategory.getId().compareTo(categoryId) == 0) {
                        String ancestors = infoBaseCategory.getAncestors();
                        //截取成数组
                        parentIds = Arrays.asList(ancestors.split(","));
                        break;
                    }
                }
            }
            for (Object o : cacheList) {
                for (String parentId : parentIds) {
                    if (o instanceof InfoBaseCategory) {
                        InfoBaseCategory infoBaseCategory = (InfoBaseCategory) o;
                        if (!"0".equals(parentId)) {
                            if (parentId.equals(String.valueOf(infoBaseCategory.getId()))) {
                                result.append("/" + infoBaseCategory.getCategoryName());
                                break;
                            }
                        }
                    }
                }
            }
            for (Object o : cacheList) {
                if (o instanceof InfoBaseCategory) {
                    InfoBaseCategory infoBaseCategory = (InfoBaseCategory) o;
                    if (categoryId.equals(infoBaseCategory.getId())) {
                        lastCategoryName = infoBaseCategory.getCategoryName();
                        break;
                    }
                }
            }
        }
        String resultStr = result.toString();
        if (StringUtils.isNotEmpty(resultStr)) {
            resultStr = (resultStr + "/" + lastCategoryName).replaceFirst("/", "");
        } else {
            resultStr = lastCategoryName;
        }
        return resultStr;
    }

    @Override
    public String getBaseCategoryByParentId(Long parentId) {
        InfoBaseCategory infoBaseCategory = new InfoBaseCategory();
        infoBaseCategory.setParentId(parentId);
        List<InfoBaseCategory> infoBaseCategories = infoBaseCategoryMapper.selectInfoBaseCategoryList(infoBaseCategory);
        List<String> ids = new ArrayList<>();
        for (InfoBaseCategory baseCategory : infoBaseCategories) {
            ids.add(String.valueOf(baseCategory.getId()));
        }
        ids.add(String.valueOf(parentId));
        return String.join(",", ids);
    }

    @Override
    public InfoBaseCategory selectInfoBaseCategory(InfoBaseCategory infoBaseCategory) {
         return infoBaseCategoryMapper.selectInfoBaseCategory(infoBaseCategory);
    }
}
